﻿// (c) Copyright Damian Mehers http://damianblog.com/
// This source is subject to the Microsoft Public License.
// See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
// All other rights reserved.

using System;
using System.Diagnostics;
using System.Net;
using System.Threading;

namespace MceFM.Last {
  [Serializable]
  public class Track : IComparable {
    private string album;
    private string buyUrl;

    [NonSerialized] private byte[] content;

    private int contentLength = -1;
    private string creator;
    private bool downloadError = false;
    private int duration;
    private string image;
    private byte[] imageData;
    private string imageDataType;
    private bool imageDownloadComplete = false;
    private readonly object imageDownloadLock = new object();
    private string location;
    private string title;
    private string lastFmTrackAuth;

    public byte[] Content {
      get {return content;}
      set {
        lock(this) {
          content = value;
          Monitor.Pulse(this);
        }
      }
    }

    public bool DownloadError {
      get {return downloadError;}
      set {
        lock(this) {
          downloadError = value;
        }
      }
    }

    public int ContentLength {
      get {return contentLength;}
      set {
        lock(this) {
          contentLength = value;
          Monitor.Pulse(this);
        }
      }
    }


    public string Location {
      get {return location;}
      set {location = value;}
    }

    public string Title {
      get {return title;}
      set {title = value;}
    }

    public string Album {
      get {return album;}
      set {album = value;}
    }

    public string Creator {
      get {return creator;}
      set {creator = value;}
    }

    public int Duration {
      get {return duration;}
      set {duration = value;}
    }

    public string BuyUrl {
      get {return buyUrl;}
      set {buyUrl = value;}
    }


    public string Image {
      get {return image;}
      set {image = value;}
    }

    public byte[] ImageData {
      get {
        lock(imageDownloadLock) {
          while(!imageDownloadComplete) {
            Trace.WriteLine("Waiting for download to complete of image : " + image);
            Monitor.Wait(imageDownloadLock);
          }
        }

        return imageData;
      }
    }

    public string ImageDataType {
      get {return imageDataType;}
    }

    public string LastFmTrackAuth {
      get {return lastFmTrackAuth;}
      set {lastFmTrackAuth = value;}
    }

    public int WaitForContent(int oldContentLength) {
      lock(this) {
        while(!downloadError && oldContentLength == contentLength && (content == null || contentLength < content.Length)) {
          Monitor.Wait(this);
        }
        return contentLength;
      }
    }

    public override string ToString() {
      return title + " from '" + album + "' by " + creator;
    }

    public override bool Equals(object obj) {
      Track other = obj as Track;
      if(other == null) {
        return false;
      }

      return ToString() == other.ToString();
    }

    public override int GetHashCode() {
      return ToString().GetHashCode();
    }

    public void DownloadImage(WebClient webClient) {
      using(webClient) {
        if(!string.IsNullOrEmpty(image)) {
          webClient.DownloadDataCompleted += webClient_DownloadDataCompleted;
          Trace.WriteLine("Downloading image : " + image);
          webClient.DownloadDataAsync(new Uri(image));
        } else {
          lock(imageDownloadLock) {
            imageDownloadComplete = true;
            Monitor.PulseAll(imageDownloadLock);
          }
        }
      }
    }

    private void webClient_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e) {
      Trace.WriteLine("Downloaded image : " + image + " with response " + e.Error);
      if(e.Error == null) {
        imageDataType = ((WebClient)sender).ResponseHeaders[HttpResponseHeader.ContentType];
        imageData = e.Result;
      }
      lock(imageDownloadLock) {
        imageDownloadComplete = true;
        Monitor.PulseAll(imageDownloadLock);
      }
    }


    public int CompareTo(object obj) {
      if (obj is Track)
      {
        Track otherTrack = (Track)obj;
        return ToString().CompareTo(otherTrack.ToString());
      }
      else
      {
        throw new ArgumentException("object is not a Track");
      }    

    }
  }
}